package run

import (
	"go-redis/utils"
	"os"
	"time"
)

const (
	SYNC_ALWAYS   = "always"
	SYNC_EVERYSEC = "every_second"
	SYNC_NO       = "no"
)

type AofPersistent struct {
	strategy    string
	CmdChan     chan string
	ResultChan  chan string
	FilePath    string
	FileHandler *os.File
	Buffer      []string
}

func NewAofPersistent(strategy string, cmd chan string, result chan string, file string) (a *AofPersistent, err error) {
	aof := AofPersistent{
		strategy:   strategy,
		CmdChan:    cmd,
		ResultChan: result,
		FilePath:   file,
	}
	var handler *os.File
	if handler, err = os.OpenFile(aof.FilePath+"tmp.aof", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err != nil {
		utils.Log.Error("can not open aof file")
		return nil, err
	}
	aof.FileHandler = handler
	a = &aof
	return a, nil
}

func (a *AofPersistent) WriteToDisk() (err error) {
	for _, message := range a.Buffer {
		_, err := a.FileHandler.WriteString(message + "\n")
		if err != nil {
			return err
		}
	}
	a.Buffer = nil
	err = a.FileHandler.Sync()
	if err != nil {
		return err
	}
	return nil
}
func (a *AofPersistent) Start() {
	if a.strategy == SYNC_ALWAYS {
		for {
			a.Buffer = append(a.Buffer, <-cmd)
			err := a.WriteToDisk()
			a.ResultChan <- "ok"
			if err != nil {
				utils.Log.Error("write aof error" + err.Error())
				return
			}
		}
	}
	if a.strategy == SYNC_EVERYSEC {
		timer := time.NewTicker(time.Second)
		for {
			select {
			case <-timer.C:
				utils.Log.Debug("write aof file....")
				err := a.WriteToDisk()
				if err != nil {
					utils.Log.Error("write aof error")
					return
				}
			default:
				select {
				case t := <-cmd:
					a.Buffer = append(a.Buffer, t)
					a.ResultChan <- "ok"
				default:
				}
			}
		}
	}
	if a.strategy == SYNC_NO {
		for {
			select {
			case <-cmd:
				a.ResultChan <- "ok"
			default:
			}
		}
	}
}

func (a *AofPersistent) ShutDown() {
	defer a.FileHandler.Close()
	if err := a.WriteToDisk(); err != nil {
		utils.Log.Error("shut down error，maybe lose data")
	}
}
